package top.goldenyear.porpoise.framework.web.core.filter;

import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Filter;
import org.noear.solon.core.handle.FilterChain;
import org.noear.solon.validation.ValidatorException;
import top.goldenyear.porpoise.common.core.exception.ServerException;
import top.goldenyear.porpoise.common.core.exception.ServiceException;
import top.goldenyear.porpoise.common.core.model.Ret;

import static top.goldenyear.porpoise.common.core.exception.enums.GlobalErrorCode.INTERNAL_SERVER_ERROR;

/**
 * @author airhead
 */
@Slf4j
@Component(delivered = false, tag = "adminApi", index = -1)
public class AdminExceptionFilter implements Filter {
  @Override
  public void doFilter(Context ctx, FilterChain chain) {
    try {
      chain.doFilter(ctx);
    } catch (ValidatorException e) {
      log.error("validator exception", e);

      ctx.status(e.getCode());
      ctx.outputAsJson(Ret.fail(e.getMessage()).toJson());
    } catch (ServerException e) {
      log.error("server exception", e);

      ctx.status(INTERNAL_SERVER_ERROR.getCode());

      Ret ret = getRet(e.getCode(), e.getMessage());
      ctx.outputAsJson(ret.toJson());
    } catch (ServiceException e) {
      log.error("service exception", e);

      ctx.status(INTERNAL_SERVER_ERROR.getCode());
      Ret ret = getRet(e.getCode(), e.getMessage());
      ctx.outputAsJson(ret.toJson());
    } catch (Throwable e) {
      log.error("other throwable", e);

      ctx.status(INTERNAL_SERVER_ERROR.getCode());
      ctx.outputAsJson(Ret.fail(INTERNAL_SERVER_ERROR.getMsg()).toJson());
    }
  }

  @NotNull
  private Ret getRet(Integer code, String msg) {
    Ret ret = Ret.fail();
    if (code != null) {
      ret.setMsg(String.format("[%d] %s", code, msg));
      ret.set("code", code);
    } else {
      ret.setMsg(
          String.format(
              "[%d] %s", INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()));
      ret.set("code", INTERNAL_SERVER_ERROR.getCode());
    }

    return ret;
  }
}
